﻿/*----------------------------------------------------------------------------------------
*
*  Copyright 2019, Gao Hai Hui, <fromzeropoint@126.com>.  All rights reserved.
*  https://gitee.com/helloworldghh/xoskit.git
*  Use of this source code is governed by a MIT license
*  that can be found in the License file.
*
----------------------------------------------------------------------------------------*/
#include "../import/head.h"
#include "../impl/head.h"
#include "big_buf_impl.h"

namespace xos_box
{
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 

    static big_buf_impl::POOL * pool_ptr = 0;

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    big_buf_impl::big_buf_impl()
    {
        m_nLen = 0;
        m_nPos = 0;
    }

    big_buf_impl::~big_buf_impl()
    {
        term();
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 

    int big_buf_impl::get_addr( POOL *** pppPool, LIST *** pppList )
    {
        int ret = 0;
        if( pppPool )
        {
            *pppPool = &pool_ptr;
        }
        if( pppList )
        {
            *pppList = 0;
        }
        return ret;
    }

    int big_buf_impl::init()
    {
        int nRet = 0;
        return nRet;
    }

    int big_buf_impl::term()
    {
        int nRet = 0;
        m_nLen = 0;
        m_nPos = 0;
        return nRet;
    }

	////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 

    // 
    // read data
    // 
	// 
	// read data
	// 
	char * big_buf_impl::get_data( char * lpszData, int nLen, int * lpnLenNeeded )
	{
		if( lpszData && ( nLen >= m_nLen ) )
		{
			memcpy( lpszData, m_szBuf + m_nPos, m_nLen );
		}
		if( lpnLenNeeded )
		{
			*lpnLenNeeded = m_nLen;
		}
		return m_szBuf + m_nPos;
	}

	int big_buf_impl::get_data( xos_box::i_big_buf * pBuf, int * lpnLenNeeded )
	{
		int ret = 0;
        ret = pBuf->set_data( m_szBuf + m_nPos, m_nLen );
		if( lpnLenNeeded )
		{
			*lpnLenNeeded = m_nLen;
		}
		return ret;
	}

	int big_buf_impl::get_data( xos_box::i_buf * pBuf, int * lpnLenNeeded )
	{
		int ret = 0;
        ret = pBuf->set_data( m_szBuf + m_nPos, m_nLen );
		if( lpnLenNeeded )
		{
			*lpnLenNeeded = m_nLen;
		}
		return ret;
	}

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 

    // 
    // set data
    // 
    int big_buf_impl::set_data( const char * lpszData, int nLen )
    {
		int ret = 0;
		if( ( 0 == ret ) && ( nLen > BUF_SIZE ) )
		{
			ret = 1;
		}
		if( 0 == ret )
		{
			memcpy( m_szBuf, lpszData, nLen );
			m_nLen = nLen;
			m_nPos = 0;
		}
		return ret;
    }

    int big_buf_impl::set_str( const char * lpszData )
    {
		int ret = 0;
        xos::i_crt * pCrt = 0;
        mgr::xos()->create( xos::i_xos::XOS_OBJ_CRT, ( void** )&pCrt );
        int len = pCrt->strlen( lpszData );
        ret = set_data( lpszData, len );
        xos_stl::release_interface( pCrt );
		return ret;
    }

	int big_buf_impl::set_data( xos_box::i_big_buf * pBuf )
	{
		int ret = 0;
		int len = 0;
		const char * lpszData = pBuf->get_data( 0, 0, &len );
		ret = set_data( lpszData, len );
		return ret;
	}

	int big_buf_impl::set_data( xos_box::i_buf * pBuf )
	{
		int ret = 0;
		int len = 0;
		const char * lpszData = pBuf->get_data( 0, 0, &len );
		ret = set_data( lpszData, len );
		return ret;
	}

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 

	int big_buf_impl::remove_data( char * lpszData, int nWantRemoveSize )
	{
		int ret = 0;
		if( ( 0 == ret ) && ( m_nLen < nWantRemoveSize ) )
		{
			ret = 1;
		}
		if( 0 == ret )
		{
			memcpy( lpszData, m_szBuf + m_nPos, nWantRemoveSize );
			m_nLen -= nWantRemoveSize;
			m_nPos += nWantRemoveSize;
		}
		return ret;
	}

	int big_buf_impl::remove_data( xos_box::i_big_buf * pBuf, int nWantRemoveSize )
	{
		int ret = 0;
		int nLen = 0;
		char * lpszData = pBuf->get_data( 0, 0, &nLen );
		int nPos = pBuf->get_pos( 0 );
		if( ( 0 == ret ) && ( nWantRemoveSize > BUF_SIZE - nPos - nLen ) )
		{
			ret = 1;
		}
		if( 0 == ret )
		{
			ret = remove_data( lpszData + nLen, nWantRemoveSize );
		}
		if( 0 == ret )
		{
			pBuf->set_len( nLen + nWantRemoveSize );
		}
		return ret;
	}

	int big_buf_impl::remove_data( xos_box::i_buf * pBuf, int nWantRemoveSize )
	{
		int ret = 0;
		int nLen = 0;
		char * lpszData = pBuf->get_data( 0, 0, &nLen );
		int nPos = pBuf->get_pos( 0 );
		if( ( 0 == ret ) && ( nWantRemoveSize > BUF_SIZE - nPos - nLen ) )
		{
			ret = 1;
		}
		if( 0 == ret )
		{
			ret = remove_data( lpszData + nLen, nWantRemoveSize );
		}
		if( 0 == ret )
		{
			pBuf->set_len( nLen + nWantRemoveSize );
		}
		return ret;
	}

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 

	int big_buf_impl::add_data( const char * lpszData, int nLen )
	{
		int ret = 0;
		if( ( 0 == ret ) && ( nLen + m_nPos + m_nLen > BUF_SIZE ) )
		{
			ret = 1;
		}
		if( 0 == ret )
		{
			memcpy( m_szBuf + m_nPos + m_nLen, lpszData, nLen );
			m_nLen += nLen;
		}
		return ret;
	}

	int big_buf_impl::add_str( const char * lpszData )
	{
        int ret = 0;
        xos::i_crt * pCrt = 0;
        mgr::xos()->create( xos::i_xos::XOS_OBJ_CRT, ( void** )&pCrt );
        int len = pCrt->strlen( lpszData );
        ret = add_data( lpszData, len );
        xos_stl::release_interface( pCrt );
        return ret;
	}

	int big_buf_impl::add_data( xos_box::i_big_buf * pBuf )
	{
		int ret = 0;
		int nLen = 0;
		char * lpszData = pBuf->get_data( 0, 0, &nLen );
		ret = add_data( lpszData, nLen );
		return ret;
	}

	int big_buf_impl::add_data( xos_box::i_buf * pBuf )
	{
		int ret = 0;
		int nLen = 0;
		char * lpszData = pBuf->get_data( 0, 0, &nLen );
		ret = add_data( lpszData, nLen );
		return ret;
	}

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 

    int big_buf_impl::get_data_from_list( xos_box::i_list * pList )
    {
        int ret = 0;
        xos_box::i_buf * pBuf = 0;
        while( ( 0 == ret ) && ( pBuf = ( xos_box::i_buf* )pList->front(0) ) )
        {
            int r = add_data( pBuf );
            if( 0 == r )
            {
                xos_stl::release_interface( pBuf );
                pList->pop_front();
            }
            else
            {
                break;
            }
        }
        return ret;
    }

    int big_buf_impl::put_data_to_list( xos_box::i_list * pList, bool bFront )
    {
        int ret = 0;
        typedef xos_stl::auto_list< xos_box::i_buf > BUF_LIST;
        BUF_LIST tmp_list;
        while( ( 0 == ret ) && ( get_len( 0 ) > 0 ) )
        {
            xos_box::i_buf * pBuf = 0;
            mgr::get()->create( enumObj::BOX_OBJ_BUF, ( void** )&pBuf );
            int left_len = get_len( 0 );
            int remove_len = left_len > BUF_SIZE ? BUF_SIZE : left_len;
            remove_data( pBuf, remove_len );
            tmp_list.push_back( pBuf );
        }
        while( ( 0 == ret ) && ( tmp_list.size() > 0 ) )
        {
            xos_box::i_buf * pBuf = 0;
            if( bFront )
            {
                pBuf = tmp_list.back();
                tmp_list.pop_back();
                pList->push_front( pBuf );
            }
            else
            {
                pBuf = tmp_list.front();
                tmp_list.pop_front();
                pList->push_back( pBuf );
            }
        }
        tmp_list.put_back_to_pool( true );
        return ret;
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 

	int big_buf_impl::move_data_to_begin()
	{
		int ret = 0;
		if( ( m_nPos != 0 ) && ( m_nLen > 0 ) )
		{
			::memmove( m_szBuf, m_szBuf + m_nPos, m_nLen );
		}
		m_nPos = 0;
		return ret;
	}

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 

    // 
    // get data len
    // 
    int big_buf_impl::get_len( int * lpnDataLen )
    {
        if( lpnDataLen )
        {
            *lpnDataLen = m_nLen;
        }
        return m_nLen;
    }

    // 
    // set data len
    // 
    int big_buf_impl::set_len( int nLen )
    {
        int nRet = 0;
        m_nLen = nLen;
        return nRet;
    }

    // 
    // get data pos
    // 
    int big_buf_impl::get_pos( int * lpnPos )
    {
        if( lpnPos )
        {
            *lpnPos = m_nPos;
        }
        return m_nPos;
    }

    // 
    // set data pos
    // 
    int big_buf_impl::set_pos( int nPos )
    {
        int nRet = 0;
        m_nPos = nPos;
        return nRet;
    }

    // 
    // get buf size. total buf size
    // 
    int big_buf_impl::get_buf_size( int * lpnBufLen )
    {
        if( lpnBufLen )
        {
            *lpnBufLen = sizeof( m_szBuf );
        }
        return sizeof( m_szBuf );
    }
} // xos
